package cluster;

//import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
public class LookupTable<E extends Clusterable> {
	

	/**
	 * Logger for this class
	 */
	//private static final Logger logger = Logger.getLogger(LookupTable.class);

	Hashtable<Key, Float> table;

	public LookupTable(int size){
		table = new Hashtable<Key, Float>(size + size / 2, 0.8f);

	}
	
	public LookupTable(ArrayList<Duster<E>> list){
		this(list.size());
		Iterator<Duster<E>> i = list.iterator();
		while(i.hasNext()) {
			addDistances(i.next(), list);
		}
	}
	
	public void addDistances(Duster<E> d, ArrayList<Duster<E>> list){

		Iterator<Duster<E>> i = list.iterator();
		while(i.hasNext()){
			Duster<E> next = i.next();
			if(d.ID != next.ID)
				addDistance(d, next);
		}
	}
	
	public void addDistance(Duster<E> d1, Duster<E> d2){
		if(d1.ID == d2.ID) return;
		Key key = new Key<E>(d1, d2);
		if(table.containsKey(key)) return;
		table.put(key, new Float(d1.getDistanceTo(d2)));
	}
	
	public void addDistance(Duster<E> d1, Duster<E> d2, float dist){
		if(d1.ID == d2.ID) return;
		Key key = new Key<E>(d1, d2);
		if(table.containsKey(key)) return;
		table.put(key, new Float(dist));
	}


	public void removeDuster(Duster<E> d){
//		if (logger.isDebugEnabled()) {
//			logger.debug("removeDuster(Duster<E>) - ID=" + d.ID + " clr: " + d.centroid.toString());
//		}

		Enumeration<Key> keys = table.keys();
		ArrayList<Key> remKeys = new ArrayList<Key>();
		while(keys.hasMoreElements()) {
			Key key = keys.nextElement();
			if(key.d1.ID == d.ID || key.d2.ID == d.ID)
				remKeys.add(key);
		}
		Iterator<Key> rem = remKeys.iterator();
		while(rem.hasNext()) {
			Key next = rem.next();
			table.remove(next);
		}
	}
	
	public Key getClosestLink(){
		Enumeration<Key> keys = table.keys();
		Key closest = null;
		float minDist = Float.MAX_VALUE;
		while(keys.hasMoreElements()){
			Key key = keys.nextElement();
			float dist = table.get(key).floatValue();
			if(dist < minDist){
				closest = key;
				minDist = dist;
			}
		}
		return closest;
	}

	public float getDistance(Duster<E> d1, Duster<E> d2){
		return getDistance(new Key<E>(d1, d2));
	}
	
	public float getDistance(Key key){
		if(!table.containsKey(key)) return Float.NaN;
		return table.get(key).floatValue();
	}
	
	
}
